const app = getApp()
function inArray(arr, key, val) {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i][key] === val) {
      return i;
    }
  }
  return -1;
}

// ArrayBuffer转16进制字符串
function buf2hex(buffer) {
  var hexArr = Array.prototype.map.call(
    new Uint8Array(buffer),
    function (bit) {
      return ('00' + bit.toString(16)).slice(-2)
    }
  )
  return hexArr.join('');
}

// 16进制字符串转ArrayBuffer
function hex2buf(hex) {
  return new Uint8Array(hex.match(/[\da-f]{2}/gi).map((h) => {
    return parseInt(h, 16)
  })).buffer
}

// 字符串转成2个一组的字符串协议的数组方便获取数据
function buffer2xy(buffer) {
  let dataView = new DataView(buffer)
  let dataResult = []
  for (let i = 0; i < dataView.byteLength; i++) {
    dataResult.push(dataView.getUint8(i).toString(16))
  }
  return dataResult
}
 
import { encryptionData, decryptData } from '../../utils/encAndDes' //加密解密


Page({
  data: { // 蓝牙设备数据
    devices: [], // 设备数据
    connected: false,
    chs: [],
    typel:'', // 输入的命令类型
    token: '', // 获取token
    power: '', // 获取电量
  },
  openBluetoothAdapter(e) { // 开始扫描
  console.log(e)
    wx.openBluetoothAdapter({ // 扫描附近的蓝牙设备
      success: (res) => {
        console.log('openBluetoothAdapter success', res)
        this.startBluetoothDevicesDiscovery()
      },
      fail: (res) => {
        if (res.errCode === 10001) {
          wx.onBluetoothAdapterStateChange(function (res) {
            console.log('onBluetoothAdapterStateChange', res)
            if (res.available) {
              this.startBluetoothDevicesDiscovery()
            }
          })
        }
      }
    })
  },
  getBluetoothAdapterState() {
    wx.getBluetoothAdapterState({ //获取本机蓝牙适配器状态。
      success: (res) => {
        console.log('getBluetoothAdapterState', res)
        if (res.discovering) {
          this.onBluetoothDeviceFound()
        } else if (res.available) {
          this.startBluetoothDevicesDiscovery()
        }
      }
    })
  },
  startBluetoothDevicesDiscovery() { // 开始搜寻附近的蓝牙外围设备
    if (this._discoveryStarted) {
      return
    }
    this._discoveryStarted = true
    wx.startBluetoothDevicesDiscovery({ // 开始搜寻附近的蓝牙外围设备
      services: ['FEE7'],
      allowDuplicatesKey: true,
      success: (res) => {
        console.log('startBluetoothDevicesDiscovery success', res)
        this.onBluetoothDeviceFound()
      },
    })
  },
  stopBluetoothDevicesDiscovery() {
    wx.stopBluetoothDevicesDiscovery()
  },
  onBluetoothDeviceFound() { // 成功返回附近的蓝牙设备
    wx.onBluetoothDeviceFound((res) => {
      res.devices.forEach(device => {
        if (!device.name && !device.localName) {
          return
        }
        const foundDevices = this.data.devices
        const idx = inArray(foundDevices, 'deviceId', device.deviceId)
        const data = {}
        if (idx === -1) {
          data[`devices[${foundDevices.length}]`] = device
        } else {
          data[`devices[${idx}]`] = device
        }
        console.log(data, '返回的设备数据')
        this.setData(data)
      })
    })
  },
  createBLEConnection(e) { 
    const ds = e.currentTarget.dataset
    const deviceId = ds.deviceId // 设备id
    const name = ds.name // 设备名称
    wx.createBLEConnection({ // 链接低功耗设备
      deviceId,
      success: (res) => {
        this.setData({
          connected: true, // 链接成功了
          name,
          deviceId,
        })
        this.getBLEDeviceServices(deviceId)
      }
    })
    this.stopBluetoothDevicesDiscovery() // 停止搜寻附近的蓝牙外围设备(搜索成功后停止搜索附近的蓝牙设备)
  },
  closeBLEConnection() {
    wx.closeBLEConnection({
      deviceId: this.data.deviceId
    })
    this.setData({
      connected: false,
      chs: [],
      canWrite: false,
    })
  },
  getBLEDeviceServices(deviceId) { // 为了获取 =》uuid
    wx.getBLEDeviceServices({ // 获取蓝牙设备所有服务
      deviceId,
      success: (res) => {
        for (let i = 0; i < res.services.length; i++) {
          if (res.services[i].isPrimary) {
            this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid) //获取蓝牙设备某个服务中所有特征值
            return
          }
        }
      }
    })
  },
  getBLEDeviceCharacteristics(deviceId, serviceId) {
    wx.getBLEDeviceCharacteristics({ //获取蓝牙设备某个服务中所有特征值
      deviceId,
      serviceId,
      success: (res) => {
        console.log('getBLEDeviceCharacteristics success', res.characteristics)
        for (let i = 0; i < res.characteristics.length; i++) {
          let item = res.characteristics[i]
          if (item.properties.read) { // 支持可读
            wx.readBLECharacteristicValue({ // 读取低功耗蓝牙设备的特征值的二进制数据值
              deviceId,
              serviceId,
              characteristicId: item.uuid,
              success: function (res) {
                console.log(res, '蓝牙设备读出来的数据')
              },
              fail: function(res){
                console.log(res, '读取蓝牙数据失败')
              }
            })
          }
          if (item.properties.write) { // 支持可写
            this.setData({
              canWrite: true
            })
            this._deviceId = deviceId
            this._serviceId = serviceId
            this._characteristicId = item.uuid
            // this.writeBLECharacteristicValue() //给蓝牙设备写入数据
          }
          if (item.properties.notify || item.properties.indicate) {
            wx.notifyBLECharacteristicValueChange({
              deviceId,
              serviceId,
              characteristicId: item.uuid,
              state: true,
            })
          }
        }
      },
      fail(res) {
        console.error('getBLEDeviceCharacteristics', res)
      }
    })

   
    // 操作之前先监听，保证第一时间获取数据
    wx.onBLECharacteristicValueChange((characteristic) => {
      console.log(characteristic, '特征值对象')
      var _v = buffer2xy(hex2buf(decryptData(buf2hex(characteristic.value))))
      console.log(_v, '返回通信帧', this.data.typel)
      switch (this.data.typel) {
        case 'token': // 获取token
          this.setData({
            token: _v.slice(3, 7).join('')
          })
          console.log(this.data.token, 'token')
          break;
        case 'power': // 获取电量
          this.setData({
            power: _v.slice(3, 4).join('')
          })
          console.log(this.data.power, '电量')
          break;
        case 'openLock': // 开锁
          this.setData({
            power: _v.slice(3, 4).join('')
          })
          console.log(this.data.power, '开锁状态')
          break;
      }
 
      const idx = inArray(this.data.chs, 'uuid', characteristic.characteristicId)
      const data = {}
      if (idx === -1) {
        data[`chs[${this.data.chs.length}]`] = {
          uuid: characteristic.characteristicId,
          value: _v
        }
      } else {
        data[`chs[${idx}]`] = {
          uuid: characteristic.characteristicId,
          value: _v
        }
      }
      this.setData(data)
    })
  },


  _writeBLECharacteristicValue(v) {
    var hex = encryptionData(v);
    const buffer1 = hex2buf(hex)
    wx.writeBLECharacteristicValue({ // 向低功耗蓝牙设备特征值中写入二进制数据。
      deviceId: this._deviceId,
      serviceId: this._serviceId,
      characteristicId: this._characteristicId,
      value: buffer1,
      success: (res) => {
        // console.log(res, '写入数据成功')
      },
      fail: function (res) {
        // console.log(res, '写入数据失败')
      }
    })  
  },

  _getValue(){
    wx.readBLECharacteristicValue({ // 读取低功耗蓝牙设备的特征值的二进制数据值
      deviceId: this._deviceId,
      serviceId: this._serviceId,
      characteristicId: this._characteristicId,
      success:  (res) => {
        console.log(res, '蓝牙设备读出来的数据')
      },
      fail: function (res) {
        console.log(res, '!!读取蓝牙数据失败!!')
      }
    })
  },

  send (e){ // 发出指令
    this.setData({
      typel: e.currentTarget.dataset.typel
    })
    var v = ''
    switch (this.data.typel) {
      case 'token': //获取token
        v ='060101012D1A683D48271A18316E471A'
       break;
      case 'power': //获取电量
        v = `02010101${this.data.token}2D1A683D48271A18`
        break;
      case 'openLock': //开锁
        v = `050106303030303030${this.data.token}2D2D2D`
        break;
    }
    this._writeBLECharacteristicValue(v)
  },
  closeBluetoothAdapter() { // 结束流程
    wx.closeBluetoothAdapter()
    this._discoveryStarted = false
  },

  
})
